<?php
namespace app\data\service;
use \Firebase\JWT\JWT;
use Firebase\JWT\Key;
class JwtTokenService
{
    /**
     * 生成token
     * @param string $user 用户信息
     *  @return array
     */
    function sign_token($user){
        $key=config('jwt.key');
        $exp_time = time() + 60;//1天过期续签
        $token_info=array(
            "iss"=>$key,        //签发者 可以为空
            "iat"=>time(),      //签发时间
            "nbf"=>time()+3,
            'exp'=> $exp_time,
            "data"=>$user
        );
        $token = JWT::encode($token_info, $key, "HS256");
        $redis = redis();
        $redis->set($token, json_encode($user),3600*24*7);//7天未操作需重新登录  3600*24*7
        return $token;
    }
    /**
     * 验证token
     * @param string $token
     * @return array
     */
    function check_token($token){
        $key=config('jwt.key');
        $res=[];
        try {
            JWT::$leeway = 60;//当前时间减去60，把时间留点余地
            $decoded = JWT::decode($token, new Key($key, 'HS256') ); //HS256方式，这里要和签发的时候对应
            $res['code']=1;
            $res['data']=$decoded->data;
            return $res;
        } catch(\Firebase\JWT\SignatureInvalidException $e) { //签名不正确
            $res['code']=401;
            $res['msg']="签名不正确";
            return $res;
        }catch(\Firebase\JWT\BeforeValidException $e) { // 签名在某个时间点之后才能用
            $res['code']=401;
            $res['msg']="token失效";
            return $res;
        }catch(\Firebase\JWT\ExpiredException $e) { // token过期
            return  $this->refresh_token($token);
        }catch(\InvalidArgumentException $e) { // Key may not be empty
            $res['code']=401;
            $res['msg']="Key may not be empty";
            return $res;
        }catch(\UnexpectedValueException $e) { // Wrong number of segments
            $res['code']=401;
            $res['msg']="Wrong number of segments";
            return $res;
        }catch(\Exception $e) { //其他错误
            $res['code']=401;
            $res['msg']="未知错误";
            return $res;
        }
    }
    /**
     * 重签token
     * @param string $token
     * @return array
     */
    function refresh_token($token){
        $redis = redis();
        $res = $redis->get($token);
        if($res!=''){
            $new_token = $this->sign_token(json_decode($res,true));//重签TOKEN
            $redis->del($token);
            $redis->set($new_token,$res,3600*24*7);
            $redis->set($token.'_wait',$res,10);//存在同步,防止并发
            $data['code']=2001;
            $data['token']=$new_token;
            $data['data']=json_decode($res);
            return $data;
        }else{
            if($redis->get($token.'_wait')){
                //如果是并发来的
                $data['code']=1;
                $data['data']=json_decode($redis->get($token.'_wait'));
                return $data;
            }else{
                $data['code']=401;
                $data['msg']="token 过期";
                return $data;
            }
        }
    }
}